//挂载到Due原型上，可以通过实例直接挂载
export function initMount(Due) {
  Due.prototype.$mount = function (el) {
    let vm = this;
    let rootDom = document.querySelector(el);
    mount(vm, rootDom);
  };
}
export function mount(vm, el) {
  //进行挂载
  vm._vnode = constructorVNode(vm, el, null); //返回虚拟根节点
  prepareRender(vm, vm._vnode);
  test(vm);
  testUtil(vm);
}

import { VNode } from "../vdom/vnode.js";
import { getVNodeByTemplate, prepareRender, test,clearMap, renderNode } from "./render.js";
import { vmodel } from "./grammer/vmodel.js";
import { vforInit } from "./grammer/vfor.js";
import { mergeAttr, testUtil } from "../util/ObjectUtil.js";
import { checkVBind } from "./grammer/vbind.js";
import {checkOn} from "./grammer/von.js"


/**
 * 构造虚拟节点，深度优先遍历
 * @param {*} vm 
 * @param {*} elm 
 * @param {*} parent 
 * @returns 虚拟节点的根节点
 */
function constructorVNode(vm, elm, parent) {
  let vnode = null;
  if (elm.nodeType == 1) {
    vnode = analysisAttr(vm, elm, parent); //解决行间属性对内容的影响
  }
  if (vnode == null) {
    let children = [];
    let text = getNodeText(elm);
    let data = null;
    let nodeType = elm.nodeType;
    let tag = elm.nodeName;
    vnode = new VNode(tag, elm, children, text, data, parent, nodeType);
   
  }
  if (elm.nodeType == 1 && elm.getAttribute("env")) {
    //自己有env作用域，添加自己的局部变量
    vnode.env = parent ? mergeAttr(parent.env, JSON.parse(elm.getAttribute("env"))):{};

  } else {
    //没新的传承父级的env
    vnode.env = parent ? parent.env : {}; 
  
  }
 
  checkVBind(vm,vnode);//检查v-bind，因为v-bind需要环境变量，所以要在环境变量设置之后分析
  checkOn(vm,vnode);//绑定v-on事件
  let childs = vnode.nodeType == 0 ? vnode.temps: vnode.elm.childNodes;
  for (let i = 0; i < childs.length; i++) {
    let childNode = constructorVNode(vm, childs[i], vnode); //深度优先搜索挂载
    if (childNode instanceof VNode) {
      vnode.children.push(childNode);
    }
  }
  return vnode;
}



function getNodeText(elm) {
  if (elm.nodeType == 3) {
    return elm.nodeValue;
  } else return "";
}

function analysisAttr(vm, elm, parent) {
  let attrNames = elm.getAttributeNames();
  if (attrNames.indexOf("v-model") > -1) {
    return vmodel(vm, elm, elm.getAttribute("v-model"));
  }
  if (attrNames.indexOf("v-for") > -1) {
    return vforInit(vm, elm, parent, elm.getAttribute("v-for"));
    //返回一个虚拟节点
  }
}

//重构节点
export function rebuild(vm,template) {
  //先打回成模板型再重新构建，重新构建只从那个虚拟节点重构那一小部分。
  // console.log(template);
  let virtualNode = getVNodeByTemplate(template);
 for (let i = 0; i < virtualNode.length; i++) {
   const vnode = virtualNode[i];
   //开始重置
   vnode.parent.elm.innerHTML = ""; //清空
   vnode.parent.elm.appendChild(vnode.elm);//恢复
  
   let result = constructorVNode(vm,vnode.elm,vnode.parent); //重构
   vnode.parent.children = [result]; //添加
   clearMap(); //清空索引
   prepareRender(vm, vnode.parent);
   renderNode(vm, vnode.parent);
 }
}

